package system

import (
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/facade/runtime"
	"gitee.com/sansaniot/ssiot-core/logger"

	"ssforward/common/constant"
	"ssforward/common/enums"
	mq "ssforward/common/middleware/mqtt"
	"ssforward/common/utils"
	"ssforward/internal/data/action"
	"ssforward/internal/data/clients"
	"ssforward/internal/data/partition"
	"ssforward/internal/data/thread"
	"ssforward/internal/forward/models"
)

// 本地mq全局使用
var MqttClient *mq.Client

func InitSystemBiz() {
	// 注册业务类
	initRegistryPartition()
	// 启动数据线程
	initDataThread()
	// 启动本地mq客户端
	initMqttClient()
	// 启动转发服务客户端(mq/db)
	initForwardClient()
	// 缓存转发配置
	InitForwardCache()
}

func initRegistryPartition() {
	// 获取db
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return
	}
	// ssdevice已处理数据接收
	partition.Registry(enums.Handler.Get().Name, &action.Handle{Orm: db})
	// ssdevice设备操作广播
	partition.Registry(enums.Broadcast.Get().Name, &action.Broad{Orm: db})

}

func initDataThread() {
	// 转发客户端状态
	thread.ClientStatusThread{}.Run("ClientStatusThread")
	// 转发明细统计
	thread.ForwardDetailThread{}.Run("ForwardDetailThread")
}

func initMqttClient() {
	MqttClient = mq.NewClient()
	// 固定订阅主题
	MqttClient.InitSubscribe(constant.HandledMsgTopic, mq.TopicHandler)
	MqttClient.InitSubscribe(constant.LoginMsgTopic, mq.TopicHandler)
	MqttClient.InitSubscribe(constant.LogoutMsgTopic, mq.TopicHandler)
	MqttClient.InitSubscribe(constant.DeviceAddMsgTopic, mq.TopicHandler)
	MqttClient.InitSubscribe(constant.DeviceDeleteMsgTopic, mq.TopicHandler)
	if _, err := MqttClient.CreateClient(); err != nil {
		logger.Error("本地mqtt连接失败" + err.Error())
	}
}

func initForwardClient() {
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return
	}
	//查询转发服务
	forwardServer := models.SysForwardServer{}
	forwardServer.Orm = db
	forwardServerList := make([]models.SysForwardServer, 0)
	if err := forwardServer.FindList(&forwardServerList); err != nil {
		logger.Error(err)
		return
	}
	mqServerList := make([]models.SysForwardServer, 0)
	dbServerList := make([]models.SysForwardServer, 0)
	for i, v := range forwardServerList {
		if v.Type == enums.Mqtt.Get().Value {
			mqServerList = append(mqServerList, forwardServerList[i])
		} else if v.Type == enums.Database.Get().Value {
			dbServerList = append(dbServerList, forwardServerList[i])
		}
	}
	// 启动对应类型的客户端
	logger.Info("启动转发mqtt客户端.")
	clients.InitMqClientList(mqServerList)

	logger.Info("启动转发db连接池.")
	clients.InitDbClientList(dbServerList)
}

func InitForwardCache() {
	db := runtime.Runtime.GetDbByKey("db")
	if db == nil {
		return
	}
	//查询转发配置
	forwardRule := models.SysForwardRule{}
	forwardRule.Orm = db
	forwardRuleList := make([]models.SysForwardRule, 0)
	if err := db.Preload("ForwardServer").Find(&forwardRuleList).Error; err != nil {
		logger.Error(err)
		return
	}
	productModels := make([]string, 0)
	devSns := make([]string, 0)
	productModelConfigMap := make(map[string][]models.SysForwardRule)
	devSnConfigMap := make(map[string][]models.SysForwardRule)
	for i, v := range forwardRuleList {
		if len(v.ProductModel) > 0 {
			if !utils.StrIn(v.ProductModel, productModels) {
				productModels = append(productModels, v.ProductModel)
			}
			if _, ok := productModelConfigMap[v.ProductModel]; !ok {
				productModelConfigMap[v.ProductModel] = make([]models.SysForwardRule, 0)
			}
			productModelConfigMap[v.ProductModel] = append(productModelConfigMap[v.ProductModel], forwardRuleList[i])
		}
		if len(v.DevSn) > 0 {
			if !utils.StrIn(v.DevSn, devSns) {
				devSns = append(devSns, v.DevSn)
			}
			if _, ok := devSnConfigMap[v.DevSn]; !ok {
				devSnConfigMap[v.DevSn] = make([]models.SysForwardRule, 0)
			}
			devSnConfigMap[v.DevSn] = append(devSnConfigMap[v.DevSn], forwardRuleList[i])
		}
	}
	devList := make([]models.SysDev, 0)
	tx := db.Model(&models.SysDev{})
	if len(devSns) > 0 && len(productModels) > 0 {
		tx = tx.Where("sn in ? ", devSns).Or("product_model in ? ", productModels)
	} else if len(devSns) > 0 {
		tx = tx.Where("sn in ? ", devSns)
	} else if len(productModels) > 0 {
		tx = tx.Where("product_model in ? ", productModels)
	} else {
		return
	}
	if err := tx.Find(&devList).Error; err != nil {
		logger.Error(err)
		return
	}
	snRuleMap := make(map[string][]models.SysForwardRule)
	for _, v := range devList {
		if _, ok := snRuleMap[v.Sn]; !ok {
			snRuleMap[v.Sn] = make([]models.SysForwardRule, 0)
		}
		if rules, ok := productModelConfigMap[v.ProductModel]; ok {
			snRuleMap[v.Sn] = append(snRuleMap[v.Sn], rules...)
		}
		if rules, ok := devSnConfigMap[v.Sn]; ok {
			snRuleMap[v.Sn] = append(snRuleMap[v.Sn], rules...)
		}
	}

	for sn, rules := range snRuleMap {
		if len(rules) == 0 {
			continue
		}
		_ = env.Cache.Set(constant.ForwardConfigKey+sn, utils.InterfaceToStr(rules), -1)
	}
	logger.Info("设备转发配置缓存")
}
